package com.zrq.gencode.util;

import com.zrq.gencode.cfg.GenCfg;
import com.zrq.gencode.domain.classdata.AttributeBase;
import com.zrq.gencode.domain.classdata.ClassBase;
import com.zrq.gencode.domain.tabledata.ColumnBase;
import com.zrq.gencode.domain.tabledata.TableBase;
import com.zrq.gencode.domain.ColumnType;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.*;

/**
 * @author zhong
 * @date 2020年1月8日
 */
public class Comvlt {

	public static final String SEPARATOR_STR = "_";
	public static final String PATHPREFIX = "src/main/java/";
	public static final String POIT = ".";
	public static final String SLASH = "/";
	public static final String ENTITY_VM = "gencode/entity.java.vm";
	public static final String SERVICE_VM = "gencode/service.java.vm";
	public static final String SERVICEIMPL_VM = "gencode/serviceImpl.java.vm";
	public static final String DAO_VM = "gencode/dao.java.vm";
	public static final String WEB_VM = "gencode/web.java.vm";
	public static final String JAVA = ".java";
	private static final Logger logger = LoggerFactory.getLogger(Comvlt.class);

	/**
	 * 将表名转换为类名
	 *
	 * @param tableName 数据库表名
	 * @return 转换后的驼峰命名类名
	 */
	public static String convertClassName(String tableName) {
		// 获取配置信息：是否自动移除前缀和表前缀配置
		boolean autoRemovePre = GenCfg.isAutoRemovePre;
		String tablePrefix = GenCfg.getTablePrefix();

		// 如果配置了自动移除前缀且表前缀不为空，则移除表名中的前缀
		if (autoRemovePre && StringUtils.isNotBlank(tablePrefix)) {
			String[] searchList = StringUtils.split(tablePrefix, ",");
			String[] replacementList = emptyList(searchList.length);
			tableName = StringUtils.replaceEach(tableName, searchList, replacementList);
		}

		// 将处理后的表名转换为驼峰命名格式
		return convertToCamelCase(tableName);
	}

	/**
	 * 表信息转java
	 * @param tables 表基本信息数组
	 * @return 类基本信息列表
	 */
	public static List<ClassBase> crovTableToJava(TableBase... tables) {
		List<ClassBase> classBases = new ArrayList<>();
		for (TableBase table : tables) {
			List<AttributeBase> attributeBase = new ArrayList<>();
			ClassBase classBase = new ClassBase();
			Set<String> importList = Collections.synchronizedSet(new HashSet<>());
			// 设置类名，将表名转换为驼峰命名格式
			classBase.setClassName(convertClassName(table.getTableName()));
			List<ColumnBase> columnBases = table.getColumnBases();
			// 遍历列信息，转换为属性信息
			for (ColumnBase columnBase : columnBases) {
				AttributeBase ab = new AttributeBase();
				String javaType = ColumnType.getJavaType(columnBase.getSqlType());
				ab.setJavaType(javaType);
				ab.setName(toCamelCase(columnBase.getName()));
				// 根据Java类型添加相应的导入包
				if ("Date".equals(javaType)) {
					importList.add("java.util.Date");
				} else if ("BigDecimal".equals(javaType)) {
					importList.add("java.math.BigDecimal");
				}
				attributeBase.add(ab);
			}
			classBase.setAttributeBases(attributeBase);
			// 设置导入包列表
			if (!importList.isEmpty()) {
				classBase.setImportList(importList);
			}
			classBase.setAuthor(GenCfg.author);
			classBases.add(classBase);
		}
		return classBases;
	}

	/**
	 * 获取空数组列表
	 *
	 * @param length 长度
	 * @return 数组信息
	 */
	public static String[] emptyList(int length) {
		// 创建指定长度的字符串数组
		String[] values = new String[length];
		// 使用空字符串填充数组
		Arrays.fill(values, StringUtils.EMPTY);
		return values;
	}

	/**
	 * 类命名
	 */
	public static String convertToCamelCase(String name) {
		if (StringUtils.isBlank(name)) {
			return "";
		}

		StringBuilder result = new StringBuilder(name.length());
		String[] spnames = name.split(SEPARATOR_STR);

		for (String sp : spnames) {
			if (StringUtils.isNotBlank(sp)) {
				result.append(sp.substring(0, 1)
					              .toUpperCase());
				result.append(sp.substring(1)
					              .toLowerCase());
			}
		}

		return result.toString();
	}

	/**
	 * 驼峰式命名法
	 * @param name 输入的字符串名称
	 * @return 转换后的驼峰式命名字符串
	 */
	public static String toCamelCase(String name) {
		// 将首字母转换为小写，其余部分保持不变
		return convertToCamelCase(name).substring(0, 1)
			.toLowerCase() + convertToCamelCase(name).substring(1);
	}

	/**
	 * 批量创建目录 支持"."分割
	 *
	 * @param paths 要创建的目录路径数组，支持使用"."作为分隔符
	 */
	public static void mkdirs(String... paths) {
		// 遍历所有路径并创建对应的目录
		for (String path : paths) {
			File file = new File(path.replace(POIT, SLASH));
			if (!file.exists()) {
				// 使用目录路径作为锁，避免全局锁定
				synchronized (file.getAbsolutePath()
					.intern()) {
					if (!file.exists()) {
						file.mkdirs();
						logger.debug("create:{}", file.getPath());
					}
				}
			}
		}
	}

	/**
	 * 添加前缀并小写
	 */
	public static String prefixSupplement(String prefix, String str) {
		return (prefix + str).toLowerCase();
	}

	/**
	 * 添加"src/main/java/"前缀并小写
	 */
	public static String packageSupplement(String str) {
		return prefixSupplement(PATHPREFIX, str);
	}

	/**
	 * target不为空则返回，否则返回deft
	 */
	public static String defaultString(String target, String deft) {
		return StringUtils.isBlank(target) ? deft : target;
	}

	/**
	 * 获取目录下的指定类型文件
	 */
	public static File[] traverseSql(File dir, String type) {
		return dir.listFiles((file, name) -> name.endsWith(type));
	}
}